#include "../include/main.h"
#include<cstdlib>
#include<iostream>
#include "../include/engine/FrameBuffer.h"
#include "../include/engine/BufferOut.h"
#include "../include/Render/Render.h"
#include "../include/Render/Pipeline.h"

const char* Class_Name = "zyy-softRenderging";
const char* Window_Title = "zyy-softRendering-windows";

int WINDOW_WIDTH = 800;
int WINDOW_HEIGHT = 600;

int timerCount = 0;

void soft_rendering_process();
void drawCall(HDC hdc);
void getWindowSize(HWND hwnd);
void soft_rendering_init();

z_pipeline::Pipeline* pipline;
z_render::Render* render;


void OnPaint(HDC hdc) {
	Graphics graphics(hdc);

	Bitmap bitmap = Bitmap(WINDOW_WIDTH, WINDOW_HEIGHT);
	z_bufferout::BufferOut& instance = z_bufferout::BufferOut::getInstance();
	instance.outBufferAsBitmap(bitmap);
	graphics.DrawImage(&bitmap, 0,0, WINDOW_WIDTH, WINDOW_HEIGHT);
}



LRESULT CALLBACK WinSunProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
		HDC          hdc;
		PAINTSTRUCT  ps;
		case WM_CLOSE:
			DestroyWindow(hwnd);
			break;
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		case WM_PAINT: {
			getWindowSize(hwnd);
			hdc = BeginPaint(hwnd, &ps);
			drawCall(hdc);
			EndPaint(hwnd, &ps);
		break;
	}
	case WM_TIMER: {
		timerCount = (timerCount + 1) % 1000;
		hdc = GetDC(hwnd);
		drawCall(hdc);
		ReleaseDC(hwnd, hdc);
		break;
	}
	default:
		return DefWindowProc(hwnd, uMsg, wParam, lParam);
	}
	return 0;
}


int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) {
	
	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR           gdiplusToken;
	// Initialize GDI+.
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
	

	WNDCLASS wndcls; 
	wndcls.cbClsExtra = 0;
	wndcls.cbWndExtra = 0;
	wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndcls.hCursor = 0;
	wndcls.hIcon = 0;
	wndcls.hInstance = hInstance;
	wndcls.lpfnWndProc = WinSunProc;
	wndcls.lpszClassName = Class_Name;
	wndcls.lpszMenuName = NULL;
	wndcls.style = CS_HREDRAW | CS_VREDRAW;
	
	RegisterClass(&wndcls);

	HWND hwnd = CreateWindowEx(
		0,
		Class_Name,
		Window_Title,
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL
	);

	if (hwnd == NULL) {
		return 0;
	}

	soft_rendering_init();
	ShowWindow(hwnd, SW_SHOWNORMAL);
	UpdateWindow(hwnd);


	SetTimer(hwnd, 1, 10, 0);

	MSG msg;
	//消息监听
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	GdiplusShutdown(gdiplusToken);
	return msg.wParam;

}

void getWindowSize(HWND hwnd) {
	LPRECT rectDlg = (LPRECT)malloc(sizeof(*rectDlg));
	GetWindowRect(hwnd, rectDlg);
	if (rectDlg != nullptr) {
		WINDOW_WIDTH = (rectDlg->right - rectDlg->left);
		WINDOW_HEIGHT = (rectDlg->bottom - rectDlg->top);
	}
}


void soft_rendering_init() {
	pipline = new z_pipeline::Pipeline();
	render = new z_render::Render();
	render->setPipeline(pipline);
}

// soft-rendering process
void soft_rendering_process() {
	// 1. get framebuffer
	z_bufferout::BufferOut& instance = z_bufferout::BufferOut::getInstance();
	instance.screenHeight = WINDOW_HEIGHT;
	instance.screenWidth = WINDOW_WIDTH;
	instance.synchronous();


	// 2. bind frameBuffer
	z_frameBuffer::FrameBuffer* outBuffer = (instance.fbWait);
	
	// 3. calculate and fill outBuffer (Rendering)
	render->insertFrameBuffer(outBuffer);
	render->executeRendering();

	// 4. input buffer
	instance.renderingOver();
}

void drawCall(HDC hdc) {
	soft_rendering_process();
	OnPaint(hdc);
}

